# URL:     http://www.fiber-space.de
# Author:  Kay Schluehr <easyextend@fiber-space.de>
# Date:    12 Nov 2006
from __future__ import with_statement
import symbol as py_symbol
import token as py_token
import EasyExtend
from EasyExtend.util.path import path
import EasyExtend.eecommon as eecommon


class FSConfig(object):
    '''
    Used to supply information about the state of the langletspace
    in terms of data provided by individual langlets.
    '''
    langlet_table = [ {"offset":0, "symbol":py_symbol, "token":py_token} ]

    @classmethod
    def get_sym_name(cls, node_id):
        if node_id < 512:
            nids = [row["offset"]+node_id for row in cls.langlet_table]
        else:
            nids = [node_id]
        for row in cls.langlet_table:
            for nid in nids:
                name = row["symbol"].sym_name.get(nid)
                if name:
                    return name
        return ""

    @classmethod
    def get_tok_name(cls, node_id):
        if node_id < 512:
            nids = [row["offset"]+node_id for row in cls.langlet_table]
        else:
            nids = [node_id]
        for row in cls.langlet_table:
            for nid in nids:
                name = row["token"].tok_name.get(nid)
                if name:
                    return name
        return ""

langlets_path = path(__file__).dirname().joinpath("langlets")
own_path = path(__file__).dirname()

def get_all_langlets():
    langlet_dirs = langlets_path.dirs()
    langlets = []
    for d in langlet_dirs:
        f = d.joinpath("langlet.py")
        if f.isfile():
            langlets.append([str(d.basename()),d])
    return langlets


class LangletGenerator(object):
    def __init__(self, name, **kwds):
        self.name = name.strip()
        self.__dict__.update(kwds)

    def execute(self):
        self.create_files()
        self.print_status()

    def create_new_langlet_offset(self, default = -1):
        count = default
        fs_path  = path(__file__).dirname().joinpath("fs")
        if count<0:
            with open(fs_path) as fs:
                for line in fs.readlines():
                    if line.startswith("offset_cnt"):
                        count = int(line.split("offset_cnt = ")[1])
        count+=1

        with open(fs_path,"w") as fs:
            print >> fs, "# -- defines offset multiplicity counter --"
            print >> fs, "# This was automatically generated by fs.py"
            print >> fs, "# Hack at your own risk."
            print >> fs, ""
            print >> fs, "offset_cnt = %d"%count
        return count

    def update_symbols_and_nfa(self, pth_langlet_py):
        from EasyExtend.eegrammar import EETokenGrammar, EEGrammar
        EETokenGrammar(pth_langlet_py, {"build_nfa": True}).load_grammar()
        EEGrammar(pth_langlet_py, {"build_nfa": True}).load_grammar()
        pth_langlet = pth_langlet_py.dirname()
        l = pth_langlet.split(pth_langlet.sep)
        langlet = __import__(str(".".join(l[l.index("langlets"):]+["langlet"])), globals(), locals(), ["EasyExtend"], -1)
        eecommon.load_nfas(langlet, True, True)


    def create_files(self):
        pth_langlet = langlets_path.joinpath(self.name)
        count = self.create_new_langlet_offset()
        offset= count*512

        pth_template = own_path.joinpath("langlet_template")
        pth_conf = pth_template.joinpath("conf.py_template")

        # create new conf.py file
        conf_py = []
        with open(pth_conf) as f_conf:
            conf_py.extend(f_conf.readlines())
            for i,line in enumerate(conf_py):
                if line.find("%PROMPT%")>0:
                    if self.prompt:
                        if self.prompt.startswith('"'):
                            conf_py[i] = line.replace("%PROMPT%", self.prompt)
                        else:
                            conf_py[i] = line.replace("%PROMPT%", '"'+self.prompt+'"')
                    else:
                        conf_py[i] = line.replace("%PROMPT%", '">>> "')
                elif line.find("%OFFSET%")>0:
                    conf_py[i] = line.replace("%OFFSET%", str(offset))
                elif line.find("%LANGLET_NAME%")>0:
                    conf_py[i] = line.replace("%LANGLET_NAME%", '"'+self.name+'"')
                elif line.find("%SOURCE_EXT%")>0:
                    if not self.source_ext[0] == ".":
                        self.source_ext = "."+self.source_ext
                    conf_py[i] = line.replace("%SOURCE_EXT%", '"'+self.source_ext+'"')
                elif line.find("%COMPILED_EXT%")>0:
                    if not self.compiled_ext[0] == ".":
                        self.compiled_ext = "."+self.compiled_ext
                    conf_py[i] = line.replace("%COMPILED_EXT%", '"'+self.compiled_ext+'"')

        pth_template.copytree(pth_langlet)
        pth_conf = pth_langlet.joinpath("conf.py")
        with open(pth_conf,"w") as f_conf:
            f_conf.write("".join(conf_py))
        pth_langlet.joinpath("run.py").rename(pth_langlet.joinpath("run_"+self.name+".py"))
        pth_langlet.joinpath("conf.py_template").remove()

        # update LANGLET_OFFSET in lex_token.py
        pth_lex_token = pth_langlet.joinpath("lexdef","lex_token.py")
        pth_lex_token_template = path(pth_lex_token+"_template")
        lex_lines = open(pth_lex_token_template).readlines()
        for i, line in enumerate(lex_lines):
            if line.find("%OFFSET%")>0:
                lex_lines[i] = line.replace("%OFFSET%", str(offset))
                break
        with open(pth_lex_token, "w") as f_lex:
            f_lex.write("".join(lex_lines))
        self.update_symbols_and_nfa(pth_conf)


    def print_status(self):
        print "New langlet '%s' created:"%self.name
        print
        f_1, f_2 = langlets_path.splitall()[-2:]
        s = "    [%s]+-[%s]"%(f_1,f_2)
        print s
        white = " "*(s.find("+-")+3)
        print white+"+- [%s]"%self.name
        print white+"    +- __init__.py"
        print white+"    +- run_%s.py"%self.name
        print white+"    +- conf.py"
        print white+"    +- langlet.py"
        print white+"    +- [lexdef]"
        print white+"        +- __init__.py"
        print white+"        +- lex_symbol.py"
        print white+"        +- lex_token.py"
        print white+"        +- lex_nfa.py"
        print white+"        +- Token.ext"
        print white+"    +- [parsedef]"
        print white+"        +- __init__.py"
        print white+"        +- parse_symbol.py"
        print white+"        +- parse_token.py"
        print white+"        +- parse_nfa.py"
        print white+"        +- Grammar.ext"
        print white+"    +- [reports]"
        print white+"    +- [tests]"



